from rest_framework import mixins
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from stuapi.models import Student
from .serializers import StudentModelSerializers


# POST /demo/students/ 添加一个学生信息
# GET /demo/students/获取所有学生信息
# PATCH /demo/students/<pk>/获取一个学生信息
# PUT /demo/students/<pk>/更新一个学生信息
# DElETE /demo/students/<pk>/删除一个学生信息


class StudentApiView(APIView):
    """ApiView基本视图类"""

    def get(self, request):
        """获取所有学生信息"""
        # 1、从数据库中读取学生列表信息
        student_list = Student.objects.all()
        # 2、实例化序列化器，获取序列化对象
        serializers = StudentModelSerializers(instance=student_list, many=True)
        # 3、处理并返回数据
        return Response(serializers.data)

    def post(self, request):
        """添加一条数据"""
        # 1、获取客户端提交的数据

        # 2、实例化序列化器
        serializer = StudentModelSerializers(data=request.data)
        # 3、验证数据
        serializer.is_valid(raise_exception=True)
        # 4、返回新增的模型数据
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def patch(self, request):
        pass

    def put(self, request):
        pass

    def delete(self, request):
        pass


class StudentsInfoApiView(APIView):
    def get(self, request, pk):
        """获取一条数据"""
        # 1、获取PK，获取模型对象
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # 2、序列化
        serailizer = StudentModelSerializers(instance=student)

        # 3、返回结果
        return Response(data=serailizer.data)

    def put(self, request, pk):
        """更新数据"""
        # 1、获取PK，获取模型对象
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        # 2、获取客户端的数据
        serializer = StudentModelSerializers(instance=student, data=request.data)
        # 3、反序列化，验证数据和保存
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 4、返回结果
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def delete(self, request, pk):
        """删除数据"""
        # 1、获取要删除的模型对象删除
        try:
            Student.objects.get(pk=pk).delete()
        except Student.DoesNotExist:
            pass
        # 2、返回数据
        return Response(status=status.HTTP_204_NO_CONTENT)


class StudentGenericApiView(GenericAPIView):
    """GenericApi通用视图类"""
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializers

    def get(self, request):
        """获取所有学生信息"""
        # 1、提取数据
        # student = self.queryset.get(pk=pk)  # 获取一条
        student_list = self.get_queryset()
        # 2、序列化
        serializer = self.get_serializer(instance=student_list, many=True)
        # 3、返回数据
        return Response(serializer.data)

    def post(self, request):
        """添加数据"""
        # 1、获取客户端提交的数据
        serializer = self.get_serializer(data=request.data)
        # 2、序列化
        # 3、验证数据保存数据
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 4、返回数据
        return Response(serializer.data, status=status.HTTP_201_CREATED)


class StudentsInfoGenericApiView(GenericAPIView):
    """通用视图info类"""
    queryset = Student.objects
    serializer_class = StudentModelSerializers

    def get(self, request, pk):
        """获取一个数据"""
        # 1、序列化
        student = self.get_object()  # PK值会自动传入等同于self.get_queryset().get(pk=pk)
        # 2、返回结果
        serializer = self.get_serializer(instance=student)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk):
        """更新一条数据"""
        instance = self.get_object()
        # 2、获取客户端提交的数据
        serializer = self.get_serializer(instance=instance, data=request.data)
        # 3、序列化保存数据
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 4、返回结果
        return Response(serializer.data, status=status.HTTP_200_OK)

    def delete(self, request, pk):
        self.get_object().delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


"""
drf内置模型扩展类，结合Generic通用视图，5个视图扩展类
ListModelMixin: 查询所有数据类
CreateModelMixin: 增加数据类
DestroyModelMixin: 删除数据类
RetrieveModelMixin: 查询单个数据类
UpdateModelMixin: 更新数据类
"""


class StudentMixinView(GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin):
    queryset = Student.objects
    serializer_class = StudentModelSerializers

    def get(self, request):
        """获取所有数据"""
        return self.list(request)

    def post(self, request):
        """添加一条数据"""
        return self.create(request)


class StudentInfoMixinView(GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin,
                           mixins.DestroyModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin):
    queryset = Student.objects
    serializer_class = StudentModelSerializers

    def get(self, request, pk):
        """获取一条数据"""
        return self.retrieve(request, pk=pk)

    def post(self, request):
        """添加一条数据"""
        return self.create(request)

    def delete(self, request, pk):
        """删除一条数据"""
        return self.destroy(request, pk=pk)

    def put(self, request, pk):
        """更新一条数据"""
        return self.update(request, pk=pk)


"""
视图子类，是通用视图类和模型扩展类的子类
ListAPIView:获取所有数据
CreateAPIView,创建数据
RetrieveAPIView,获取一个数据
UpdateAPIView,更新数据
DestroyAPIView,删除一个数据
RetrieveUpdateDestroyAPIView = RetrieveAPIView + UpdateAPIView + DestroyAPIView
ListCreateAPIView = ListAPIView + CreateAPIView
"""

from rest_framework.generics import ListAPIView, CreateAPIView, \
    RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveUpdateDestroyAPIView, ListCreateAPIView


class StudentView(ListCreateAPIView):
    queryset = Student.objects
    serializer_class = StudentModelSerializers


# RetrieveAPIView, UpdateAPIView, DestroyAPIView
class StudentInfoView(RetrieveUpdateDestroyAPIView):
    queryset = Student.objects
    serializer_class = StudentModelSerializers


"""
上面的接口在实现中也存在代码重复的情况，如果合并则需要考虑
1、路由合并问题
2、get方法重复问题

drf提供了视图集解决这个问题
ViewSet --> APIView中代码重复问题
"""
from rest_framework.viewsets import ViewSet


class StudentViewSet(ViewSet):
    def get_list(self, request):
        # 1、从数据库中读取学生列表信息
        student_list = Student.objects.all()
        # 2、实例化序列化器，获取序列化对象
        serializers = StudentModelSerializers(instance=student_list, many=True)
        # 3、处理并返回数据
        return Response(serializers.data)

    def create_student(self, request):
        serializer = StudentModelSerializers(data=request.data)
        # 3、验证数据
        serializer.is_valid(raise_exception=True)
        # 4、返回新增的模型数据
        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def get_student_info(self, request, pk):
        # 1、获取PK，获取模型对象
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # 2、序列化
        serailizer = StudentModelSerializers(instance=student)

        # 3、返回结果
        return Response(data=serailizer.data)

    def update_student(self, request, pk):
        try:
            student = Student.objects.get(pk=pk)
        except Student.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
            # 2、获取客户端的数据
        serializer = StudentModelSerializers(instance=student, data=request.data)
        # 3、反序列化，验证数据和保存
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 4、返回结果
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def delete_student(self, request, pk):
        try:
            Student.objects.get(pk=pk).delete()
        except Student.DoesNotExist:
            pass
        # 2、返回数据
        return Response(status=status.HTTP_204_NO_CONTENT)


"""通用视图集"""
from rest_framework.viewsets import GenericViewSet


class StudentGenericViewSet(GenericViewSet):
    queryset = Student.objects
    serializer_class = StudentModelSerializers

    def get_list(self, request):
        """获取多个数据"""
        student_list = self.get_queryset()
        serializer = self.get_serializer(instance=student_list, many=True)
        return Response(data=serializer.data)

    def get_student(self, request, pk):
        student = self.get_object()
        serializer = self.get_serializer(instance=student)
        return Response(data=serializer.data)

    def create_student(self, request):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid()
        serializer.save()
        return Response(data=serializer.data, status=status.HTTP_201_CREATED)

    def update_student(self, request, pk):
        instance = self.get_object()
        serializer = self.get_serializer(instance=instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_200_OK)

    def delete_student(self, request, pk):
        self.get_object().delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


"""视图集+混入类"""


class StudentGenericMixinViewSet(GenericViewSet, mixins.ListModelMixin, mixins.CreateModelMixin,
                                 mixins.DestroyModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin):
    queryset = Student.objects
    serializer_class = StudentModelSerializers

    def get_list(self, request):
        """获取所有数据"""
        return self.list(request)

    def get(self, request, pk):
        """获取一条数据"""
        return self.retrieve(request, pk=pk)

    def post(self, request):
        """添加一条数据"""
        return self.create(request)

    def delete(self, request, pk):
        """删除一条数据"""
        return self.destroy(request, pk=pk)

    def put(self, request, pk):
        """更新一条数据"""
        return self.update(request, pk=pk)


"""上面的继承太多了，让ReadOnlyModelViewSet继承即可"""

from rest_framework.viewsets import ReadOnlyModelViewSet


class StudentGenericReadOnlyModelViewSet(ReadOnlyModelViewSet, RetrieveUpdateDestroyAPIView, ListCreateAPIView):
    queryset = Student.objects
    serializer_class = StudentModelSerializers


"""
ModelViewSet 
    实现了5个API接口
"""
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action


class StudentModelViewSet(ModelViewSet):
    """最终版，实现五个接口
        查询单个
        查询所有
        增加
        删除
        修改
    """
    queryset = Student.objects
    serializer_class = StudentModelSerializers

    @action(methods=["get", "post", "delete", "put"], detail=True, url_path="login")  # # 自定义方法生成路由
    def login(self, request, pk):
        """
        action: methods 调用的方法，
        detail:是否需要传值过来，True or False
        url_path:设备login作为访问路径，不指定则以方法名作为
        """
        # 视图集中比图片视图集多一个变量，action
        print(self.action)
        return Response(data={"info": "登录成功{}".format(pk)})
